package demoMod.invincibleOne.ui;

import basemod.ReflectionHacks;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.evacipated.cardcrawl.modthespire.lib.SpireEnum;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.cards.CardGroup;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.helpers.*;
import com.megacrit.cardcrawl.helpers.input.InputHelper;
import com.megacrit.cardcrawl.relics.Circlet;
import com.megacrit.cardcrawl.rewards.RewardItem;
import com.megacrit.cardcrawl.rooms.AbstractRoom;
import com.megacrit.cardcrawl.rooms.EmptyRoom;
import com.megacrit.cardcrawl.vfx.AbstractGameEffect;
import com.megacrit.cardcrawl.vfx.cardManip.PurgeCardEffect;
import demoMod.invincibleOne.InvincibleOneMod;
import demoMod.invincibleOne.actions.SelectCardInCardGroupAction;
import demoMod.invincibleOne.neow.InvincibleRewardItem;
import demoMod.invincibleOne.relics.TaskGoal;

import java.util.ArrayList;
import java.util.function.Function;

public class BingoRewardItem extends RewardItem {
    public static final String[] TEXT = CardCrawlGame.languagePack.getUIString(InvincibleOneMod.makeID("BingoRewards")).TEXT;
    public static Builder cardRewardBuilder = new Builder().setType(RewardType.CARD);
    public static Builder cardRemovalRewardBuilder = new Builder().setType(BingoRewardType.INVINCIBLE_CARD_REMOVAL);
    public static Builder legendaryCardRewardBuilder = new Builder().setType(BingoRewardType.LEGENDARY_CARD);
    public static class Builder {
        private RewardType type;
        private String description;

        public Builder setType(RewardType type) {
            this.type = type;
            if (type == RewardType.CARD) {
                description = TEXT[0];
            } else if (type == BingoRewardType.INVINCIBLE_CARD_REMOVAL) {
                description = TEXT[1];
            } else if (type == BingoRewardType.LEGENDARY_CARD) {
                description = TEXT[2];
            }
            return this;
        }

        public BingoRewardItem build() {
            BingoRewardItem ret = new BingoRewardItem(type, description);
            if (type == RewardType.CARD) {
                InvincibleOneMod.addToBot(new AbstractGameAction() {
                    @Override
                    public void update() {
                        ret.cards = InvincibleRewardItem.getRewardCards(null);
                        isDone = true;
                    }
                });
                ret.onClaimReward = item -> {
                    AbstractDungeon.cardRewardScreen.open(ret.cards, ret, TEXT[3]);
                    return false;
                };
            } else if (type == BingoRewardType.INVINCIBLE_CARD_REMOVAL) {
                ret.onClaimReward = item -> {
                    CardGroup tmp = CardGroup.getGroupWithoutBottledCards(AbstractDungeon.player.masterDeck.getPurgeableCards());
                    InvincibleOneMod.addToBot(new SelectCardInCardGroupAction(1, c -> true, c -> {
                        if (AbstractDungeon.player != null && AbstractDungeon.player.masterDeck != null) {
                            AbstractDungeon.topLevelEffects.add(new PurgeCardEffect(c, (float) Settings.WIDTH / 2.0F, (float)Settings.HEIGHT / 2.0F));
                            AbstractDungeon.player.masterDeck.removeCard(c);
                            InvincibleOneMod.bingoRewardList.getRewards().remove(ret);
                            InvincibleOneMod.bingoRewardList.claimingReward = false;
                        }
                    }, tmp, SelectCardInCardGroupAction.TEXT[4]));
                    return false;
                };
            } else if (type == BingoRewardType.LEGENDARY_CARD) {

                InvincibleOneMod.addToBot(new AbstractGameAction() {
                    @Override
                    public void update() {
                        InvincibleOneMod.legendaryCardChance[CardCrawlGame.saveSlot] = 100;
                        ret.cards = AbstractDungeon.getRewardCards();
                        InvincibleOneMod.legendaryCardChance[CardCrawlGame.saveSlot] = 0;
                        isDone = true;
                    }
                });
                ret.onClaimReward = item -> {
                    AbstractDungeon.cardRewardScreen.open(ret.cards, ret, TEXT[3]);
                    return false;
                };
            }
            return ret;
        }
    }

    private Function<RewardItem, Boolean> onClaimReward;

    private BingoRewardItem(RewardType type, String description) {
        super(new Circlet());
        this.hb = new Hitbox(460.0F * Settings.xScale, 90.0F * Settings.yScale);
        this.flashTimer = 0.0F;
        this.isDone = false;
        this.ignoreReward = false;
        this.redText = false;
        this.type = type;
        this.text = description;
    }

    @Override
    public boolean claimReward() {
        // 相关bug: 在第三幕开始未进入战斗时领Bingo奖励，会直接跳过第三幕
        if (AbstractDungeon.getCurrRoom() instanceof EmptyRoom) {
            return false;
        }

        InvincibleOneMod.bingoRewardList.claimingReward = true;
        if (onClaimReward != null) {
            return onClaimReward.apply(this);
        }
        return true;
    }

    @Override
    public void update() {
        float tmpHbX = this.hb.cX;
        if (AbstractDungeon.getCurrMapNode() == null || AbstractDungeon.getCurrRoom() == null) {
            return;
        }
        if (InvincibleOneMod.bingoRewardList.hide || AbstractDungeon.getCurrRoom().phase == AbstractRoom.RoomPhase.COMBAT || InvincibleOneMod.bingoRewardList.claimingReward) {
            this.hb.move(-9999.0F, this.hb.cY);
        }
        super.update();
        if (InvincibleOneMod.bingoRewardList.hide || AbstractDungeon.getCurrRoom().phase == AbstractRoom.RoomPhase.COMBAT || InvincibleOneMod.bingoRewardList.claimingReward) {
            this.hb.move(tmpHbX, this.hb.cY);
        }
        if (this.isDone && claimReward()) {
            InvincibleOneMod.addToBot(new AbstractGameAction() {
                @Override
                public void update() {
                    InvincibleOneMod.bingoRewardList.getRewards().remove(BingoRewardItem.this);
                    if (InvincibleOneMod.bingoRewardList.getRewards().isEmpty()) {
                        TaskGoal tg = (TaskGoal) AbstractDungeon.player.getRelic(TaskGoal.ID);
                        tg.stopPulse();
                    }
                    isDone = true;
                }
            });
        }
        this.isDone = false;
    }

    @Override
    public void move(float y) {
        this.y = y;
        this.hb.move(230.0F * Settings.xScale, y);
    }

    @Override
    public void render(SpriteBatch sb) {
        if (this.hb.hovered) {
            sb.setColor(new Color(0.4F, 0.6F, 0.6F, InvincibleOneMod.bingoRewardList.alpha));
        } else {
            sb.setColor(new Color(0.5F, 0.6F, 0.6F, 0.8F * InvincibleOneMod.bingoRewardList.alpha));
        }

        if (this.hb.clickStarted) {
            sb.draw(ImageMaster.REWARD_SCREEN_ITEM, 232.0F * Settings.xScale - 232.0F, this.y - 49.0F, 116.0F, 49.0F, 464.0F, 98.0F, Settings.xScale * 0.98F, Settings.scale * 0.98F, 0.0F, 0, 0, 464, 98, false, false);
        } else {
            sb.draw(ImageMaster.REWARD_SCREEN_ITEM, 232.0F * Settings.xScale - 232.0F, this.y - 49.0F, 116.0F, 49.0F, 464.0F, 98.0F, Settings.xScale, Settings.scale, 0.0F, 0, 0, 464, 98, false, false);
        }

        if (this.flashTimer != 0.0F) {
            sb.setColor(0.6F, 1.0F, 1.0F, this.flashTimer * 1.5F * InvincibleOneMod.bingoRewardList.alpha);
            sb.setBlendFunction(770, 1);
            sb.draw(ImageMaster.REWARD_SCREEN_ITEM, 232.0F * Settings.xScale - 232.0F, this.y - 49.0F, 116.0F, 49.0F, 464.0F, 98.0F, Settings.xScale * 1.03F, Settings.scale * 1.15F, 0.0F, 0, 0, 464, 98, false, false);
            sb.setBlendFunction(770, 771);
        }

        float rewardItemX = 48.0F * Settings.scale;
        sb.setColor(new Color(1.0F, 1.0F, 1.0F, InvincibleOneMod.bingoRewardList.alpha));
        switch (this.type) {
            case POTION:
                this.potion.renderLightOutline(sb);
                this.potion.render(sb);
                this.potion.generateSparkles(this.potion.posX, this.potion.posY, true);
                break;
            case GOLD:
            case STOLEN_GOLD:
                sb.draw(ImageMaster.UI_GOLD, rewardItemX - 32.0F, this.y - 32.0F - 2.0F * Settings.scale, 32.0F, 32.0F, 64.0F, 64.0F, Settings.scale, Settings.scale, 0.0F, 0, 0, 64, 64, false, false);
                break;
            case RELIC:
                this.relic.renderWithoutAmount(sb, new Color(0.0F, 0.0F, 0.0F, 0.25F));
                if (this.hb.hovered) {
                    if (this.relicLink != null) {
                        ArrayList<PowerTip> tips = new ArrayList<>();
                        tips.add(new PowerTip(this.relic.name, this.relic.description));
                        if (this.relicLink.type == RewardItem.RewardType.SAPPHIRE_KEY) {
                            tips.add(new PowerTip(TEXT[7], TEXT[8] + FontHelper.colorString(TEXT[6] + TEXT[9], "y")));
                        }

                        TipHelper.queuePowerTips(360.0F * Settings.scale, (float) InputHelper.mY + 50.0F * Settings.scale, tips);
                    } else {
                        this.relic.renderTip(sb);
                    }
                }
                break;
            case CARD:
                boolean isBoss = ReflectionHacks.getPrivate(this, RewardItem.class, "isBoss");
                if (isBoss) {
                    sb.draw(ImageMaster.REWARD_CARD_BOSS, rewardItemX - 32.0F, this.y - 32.0F - 2.0F * Settings.scale, 32.0F, 32.0F, 64.0F, 64.0F, Settings.scale, Settings.scale, 0.0F, 0, 0, 64, 64, false, false);
                } else {
                    sb.draw(ImageMaster.REWARD_CARD_NORMAL, rewardItemX - 32.0F, this.y - 32.0F - 2.0F * Settings.scale, 32.0F, 32.0F, 64.0F, 64.0F, Settings.scale, Settings.scale, 0.0F, 0, 0, 64, 64, false, false);
                }
                break;
        }

        if (this.type == BingoRewardType.LEGENDARY_CARD) {
            sb.draw(ImageMaster.REWARD_CARD_BOSS, rewardItemX - 32.0F, this.y - 32.0F - 2.0F * Settings.scale, 32.0F, 32.0F, 64.0F, 64.0F, Settings.scale, Settings.scale, 0.0F, 0, 0, 64, 64, false, false);
        } else if (this.type == BingoRewardType.INVINCIBLE_CARD_REMOVAL) {
            sb.draw(ImageMaster.REWARD_CARD_NORMAL, rewardItemX - 32.0F, this.y - 32.0F - 2.0F * Settings.scale, 32.0F, 32.0F, 64.0F, 64.0F, Settings.scale, Settings.scale, 0.0F, 0, 0, 64, 64, false, false);
        }

        Color color;
        if (this.hb.hovered) {
            color = Settings.GOLD_COLOR.cpy();
        } else {
            color = Settings.CREAM_COLOR.cpy();
        }

        if (this.redText) {
            color = Settings.RED_TEXT_COLOR.cpy();
        }

        color.a = InvincibleOneMod.bingoRewardList.alpha;

        FontHelper.renderSmartText(sb, FontHelper.cardDescFont_N, this.text, rewardItemX + 16.0F * Settings.scale, this.y + 5.0F * Settings.scale, 1000.0F * Settings.scale, 0.0F, color);
        if (!this.hb.hovered) {

            ArrayList<AbstractGameEffect> effects = ReflectionHacks.getPrivate(this, RewardItem.class, "effects");
            for (AbstractGameEffect e : effects) {
                e.render(sb);
            }
        }

        if (Settings.isControllerMode) {
            this.renderReticle(sb, this.hb);
        }

        this.hb.render(sb);
    }

    public static class BingoRewardType {
        @SpireEnum
        public static RewardType INVINCIBLE_CARD_REMOVAL;

        @SpireEnum
        public static RewardType LEGENDARY_CARD;
    }
}
